; 显示字符串
; ax : 输入参数，字符串地址
; cx : 输入参数，字符串长度
print:
	; 入栈
	push ax
	push bp
	push bx

	mov bp, ax      ; 保存字符串地址
	mov ax, 0x1301  ; 子功能号 0x13 是写字符串
	mov bx, 000fh   ; 页号位 0，黑底白字
	int 0x10  

	; 出栈
	pop bx
	pop bp
	pop ax

	ret    

; 功能：读取硬盘扇区并将其写入内存
; eax : 输入参数， 扇区号
; bx : 输入参数，将数据写入的内存地址
; cx : 输入参数，读取扇区数
rd_disk_to_mem:
	push eax
	push ebx
	push ecx
	push edx
	push esi
	push edi

	mov esi, eax	; 备份 eax
	mov di, cx		; 备份 cx
	
	; 第 1 步：设置要读取的扇区数
	mov dx, 0x1f2
	mov al, cl   
	out dx, al		; 读取的扇区数

	mov eax, esi	; 恢复 eax

	; 第 2 步：将 LBA 地址存入 0x1f3 ~ 0x1f6

	; LBA 地址 7 ~ 0 位写入端口 0x1f3
	mov dx, 0x1f3
	out dx, al

	; LBA 地址 15 ~ 8 位写入端口 0x1f4
	mov cl, 8
	shr eax, cl
	mov dx, 0x1f4
	out dx, al

	;  LBA 地址 23 ~ 16 位写入端口 0x1f5
	shr eax, cl
	mov dx, 0x1f5
	out dx, al

	shr eax, cl
	and al, 0x0f 	; LBA 第 24 ~ 27 位
	or al, 0xe0 	; 设置 7 ~ 4 位为 1110，表示 LBA 模式
	mov dx, 0x1f6
	out dx, al

	; 第 3 步：向 0x1f7 端口写入读命令， 0x20
	mov dx, 0x1f7
	mov al, 0x20
	out dx, al

	; 第 4 步：检测硬盘状态
.not_ready:
	; 同一端口，写时表示写入命令字，读时表示读入硬盘状态
	nop
	in al, dx
	and al, 0x88	; 第 4 位为 1 表示硬盘控制权已准备好数据传输，
					; 第 7 位为 1 表示硬盘忙
	cmp al, 0x08
	jnz .not_ready	; 若未准备好，继续等

	; 第 5 步：从 0x1f0 端口读数据
	mov ax, di
	; di 为要读取的扇区数，一个扇区有 512 字节，每次读入一个字
	; 共需 di*512/2 次，所以 di*256
	mov dx, 256
	mul dx			
	mov cx, ax
	mov dx, 0x1f0
.go_on_read:
	in ax, dx
	mov [bx], ax
	add bx, 2
	loop .go_on_read

	pop edi
	pop esi
	pop edx
	pop ecx
	pop ebx
	pop eax
	ret

	